/* 
 * Persistence4J - Simple library for data persistence using java
 * Copyright (c) 2010, Avdhesh yadav.
 * http://www.avdheshyadav.com
 * Contact: avdhesh.yadav@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package com.avdheshyadav.p4j.jdbc.dbms.metadata;

import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.avdheshyadav.spiderdb.ConfigEnum;
import com.avdheshyadav.spiderdb.DBCrawler;
import com.avdheshyadav.spiderdb.dbmodel.Column;
import com.avdheshyadav.spiderdb.dbmodel.DataBase;
import com.avdheshyadav.spiderdb.dbmodel.Schema;
import com.avdheshyadav.spiderdb.dbmodel.Table;
import com.avdheshyadav.p4j.common.DbmsType;
import com.avdheshyadav.p4j.jdbc.dbms.connfactory.DBConnector;

/**
 * @author Avdhesh Yadav
 */
public class MetaDataLoader implements IMetaDataLoader
{
	static Logger logger = Logger.getLogger(MetaDataLoader.class.getName());
	//
	private HashMap<String, Map<String, TableStructure>> mSchemaMap;
	//
	private DBConnector m_DbConnector;
	
	/**
	 * 
	 * @param connector DBConnector
	 * 
	 * @throws Exception
	 */
	public MetaDataLoader(DBConnector connector) throws Exception
	{
		m_DbConnector = connector;
		mSchemaMap = new HashMap<String, Map<String, TableStructure>>();
		load(); 
	}
	

	/**
	 * Loads Database Tables
	 * 
	 */
	private void load() throws Exception
	{
		logger.info("Inside load method info");
		DataBase database = getDatabase();
		Set<Schema> schemas =  database.getSchemaSet().getSchemas();
		String productName = database.getProductName();
		for(Schema schema : schemas)
		{
			String schemaName = schema.getSchamaName();
			schemaName = schemaName.toLowerCase();
			//In case of product is MySql then database name and schema are same thing.But for the Postgres it is database.schema.table.			
			if(productName != null && productName.equalsIgnoreCase(DbmsType.MYSQL) && !schemaName.equals(m_DbConnector.getDatabaseName()))
				continue;
			
			Set<Table> tables = schema.getTableSet().getTables();
			logger.info("schemaName:" + schemaName +" tables:"+tables.size());
			Map<String, TableStructure> tableMap = new HashMap<String, TableStructure>();
				
			for (Table table : tables)
			{
				logger.info("tableName:"+table.getTableName().toLowerCase());
				TableStructure tableStructure = new TableStructure(schemaName,table.getTableName().toLowerCase(),table.getPrimaryKey(),null);
				tableStructure.setForeignKey(null);
				Set<Column> columns = table.getColumnSet().getColumns();
				for (Column column: columns)
				{
					tableStructure.addColumn(column);
				}
				tableStructure.createQueries();
				tableMap.put(tableStructure.getTableName(), tableStructure);
			}
			mSchemaMap.put(schemaName, tableMap);
		}
		logger.info("Exiting Load method");
	}

	
	/**
	 * 
	 */
	public TableStructure getTableStructure(String schemaName, String tableName)
	{
		if(mSchemaMap.containsKey(schemaName))
		{
			Map<String, TableStructure> mTableMap  = mSchemaMap.get(schemaName);
			return mTableMap.get(tableName);
		}
		return null;
	}
	
	
	/**
	 * 
	 * @return DataBase
	 * 
	 * @throws Exception
	 */
	private DataBase getDatabase() throws Exception
	{
		Connection connection = m_DbConnector.getConnection();
		try 
		{
			DBCrawler dbCrawler = new DBCrawler(connection, ConfigEnum.MINIMUM);
			return dbCrawler.getDatabase();
		} 
		finally
		{
			if(connection != null)
				connection.close();
		}
	}
	
	
	/**
	 * 
	 * @return DBConnector
	 */
	public DBConnector  getDBConnector()
	{
		return m_DbConnector;
	}
}